import React,{useState,useMemo} from 'react'

// useMemo
// 基本用法
// useMemo(create,deps)函数通常传入2个参数，第一个参数为我们定义的一个包含复杂计算且有返回值的函数
// 第2个参数为该处理函数中存在的依赖变量

// useMemo只是理论上进行组件计算性能优化，但react并不能百分比保证安装预期执行，比如网页处于离屏（休眠。挂起）
// 等状态时，react底层原型链也许就会释放（删除）之前保存的函数返回值，等到下次网页重新被唤醒时，重新计算一次

// 代码形式
// const xxxValue = useMemo(() => {
//     let result = xxxValue
//     // 经过复杂的计算后
//     return result
// },[xx])
// 1使用useMemo()将计算函数包裹住，将计算函数中使用到的数据变量作为第二个参数
// 2 计算函数体内,把计算结果以return形式返回回去
// xxxvalue为该函数返回值在react原型链上的引用

// useMemo 和useCallback的区分
// useCallback 是将某个函数放入react底层原型链上，并返回该函数的索引
// useMemo 是将某个函数返回值放入到react底层原型链上，并返回该返回值的索引
// 一个针对函数，一个针对函数返回值

// useCallback(fn,deps] 相当于 useMemo(() => fn,deps)
// 1 不是所有fn(函数)都适用，必须是函数有返回值，即函数有return xx 才可以
// 2 虽然都是fn，但是函数体内代码内容相差很大，useCallback中fn主要处理各种操作事务的代码，例如修改某变量值或加载数据等
// 而useMemo中的fn主要用来处理各种计算事务的代码
// 3 useCallBack和useMemo都是为了提升组件性能。useCallback中的函数是侧重操作事务。useMemo中的函数是侧重计算结果

// 使用示例
// 若某react组件内部有2个number类型的变量num.random，2个button,点击之后分别可以修改num,random的值，
//  与此同时，该组件中还要求显示出num范围内的所有质数个数总和

function UseMemo  () {
    const [num,setNum] = useState(2020)
    const [random,setRandom] = useState(0)
    // 通过useMemo将函数体内的计算结果（返回值）保存到react底层原型链上
    // totalprimes为react底层原型链上该函数计算结构的引用
    const totalPrimes = useMemo(() => {
        console.log('begin...') //方便验证在重新渲染时是否重新执行了一遍计算
        let total = 0
        for(let i=0;i<=num;i++) {
            let boo = true
            for (let j=2;j<i;j++) {
                if(i%j ===0) {
                    boo = false
                    break
                }
            }
            if (boo && i !==1) {
                total ++
            }
        }
        return total
    },[num])
    const clickHandler01 = () => {
        setNum(num +1)
    }
    const clickHandler02 = () => {
        setRandom(Math.floor(Math.random()*100)) //修改random的值导致整个组件重新渲染
    }
    return (
        <div>
            {num} -{totalPrimes} -{random}
            <button onClick={clickHandler01}>add+ 1</button>
            <button onClick={clickHandler02}>random</button>
        </div>
    )
}

export default UseMemo;
